#!/usr/bin/env node

import config from '../config'
import commands from './commands'
import { program } from 'commander'
import { mkdirIfNotExistSync } from '@/utils/fs'
import type { Command } from 'commander'
import type { CommandModule, OptionType } from '@/types/cli'

mkdirIfNotExistSync(config.defaultCacheDir)

program.name('fs')
program.version(config.version, '-v, --version')
program.usage('[command] [flags]')
program.option('-c, --config <path>', 'set config file path')

// 遍历命令
commands.forEach((item) => {
  if (Array.isArray(item.name)) {
    // 如果 name 是数组，则遍历数组，将每一个元素作为命令
    item.name.forEach((name) => addCommand(name, item))
  } else {
    addCommand(item.name, item)
  }
})

// 组合命令
function combinedCommand(name: string, args?: string[]) {
  let command = name
  if (args) command += ` ${args.join(' ')}`
  return command
}

function addOption(command: Command, options: OptionType[]) {
  options.forEach((option) => {
    if (option.ignore) return
    const args: any[] = [option.flags]
    if (option.description) {
      args.push(option.description)

      if (option.fn) {
        args.push(option.fn)
      } else if (option.regexp) {
        args.push(option.regexp)
      }

      if (option.defaultValue) {
        args.push(option.defaultValue)
      }
    }

    if (option.required) {
      // @ts-ignore
      command.requiredOption(...args)
    } else {
      // @ts-ignore
      command.option(...args)
    }
  })
}

// 添加命令
function addCommand(name: string, options: CommandModule) {
  const command = combinedCommand(name, options.args)
  const commandInstance = program.command(command).description(options.description || '')
  if (options.options) addOption(commandInstance, options.options)
  if (options.before) options.before(commandInstance)
  commandInstance.action((...args) => options.action(args, program.opts()))
}

// 解析参数
program.parse()
